
/// @file Defines Function Groups used in the StateClient API.
#ifndef NOSAL_EXEC_FUNCTION_GROUP_H_
#define NOSAL_EXEC_FUNCTION_GROUP_H_

#include "nosal/core/result.h"

#include <fstream>

namespace netaos {
namespace nosal {
namespace exec {
///
/// @brief Class representing Function Group defined in meta-model (ARXML).
///
/// @note Once created based on ARXML path, it's internal value stay bounded to it for entire lifetime of an object.
///
class FunctionGroup final
{
public:
    /// @brief Named constructor FunctionGroup.
    ///
    /// This method shall validate/verify meta-model path passed and perform FunctionGroup object creation.
    ///
    /// @param metaModelIdentifier stringified meta model identifier (short name path) where path separator is '/'.
    /// @returns an instance of FunctionGroup, or ExecErrc error.
    /// @error nosal::exec::ExecErrc::kMetaModelError if metaModelIdentifier passed is incorrect (e.g. FunctionGroupState
    /// identifier has been passed).
    /// @error nosal::exec::ExecErrc::kGeneralError if any other error occurs.
    ///
    static nosal::core::Result<FunctionGroup> Create(std::string metaModelIdentifier) noexcept;

    ///
    /// @brief Default constructor.
    ///
    /// @note Default constructor is deleted in favor of named constructor (Create).
    ///
    FunctionGroup() = delete;

    ///
    /// @brief Copy constructor.
    /// @note To prevent problems with resource allocations during copy operation, this class is non-copyable.
    ///
    FunctionGroup(const FunctionGroup& other) = delete;

    ///
    /// @brief Copy assignment operator.
    /// @note To prevent problems with resource allocations during copy operation, this class is non-copyable.
    ///
    FunctionGroup& operator=(const FunctionGroup& other) = delete;

    ///
    /// @brief Move constructor.
    /// @param[in] other FunctionGroup instance to move to a newly constructed object.
    FunctionGroup(FunctionGroup&& other) noexcept;

    ///
    /// @brief Move assignment operator.
    /// @param[in] other FunctionGroup instance to move to this object.
    FunctionGroup& operator=(FunctionGroup&& other) noexcept;

    ///
    /// @brief Destructor of the FunctionGroup instance.
    ///
    ~FunctionGroup() noexcept;

    ///
    /// @brief EQ operator to compare with other FunctionGroup instance.
    ///
    /// @param other - FunctionGroup instance to compare this one with.
    /// @returns true in case both FunctionGroups are representing exactly
    ///          the same meta-model element, false otherwise.
    ///
    bool operator==(const FunctionGroup& other) const noexcept;

    ///
    /// @brief UNEQ operator to compare with other FunctionGroup instance.
    ///
    /// @param other - FunctionGroup instance to compare this one with.
    /// @returns false in case both FunctionGroups are representing
    ///          exactly the same meta-model element, true otherwise.
    ///
    bool operator!=(const FunctionGroup& other) const noexcept;

private:
    /// @brief Private constructor used in Create method.
    explicit FunctionGroup(std::string metaModelIdentifier) noexcept;

    /// @brief the metaModelIdentifier of the group.
    std::string metaModelIdentifier_;

    /// @brief Allow stringification of the FunctionGroup by printing the metaModelIdentifier.
    friend std::ostream& operator<<(std::ostream& os, const FunctionGroup& group)
    {
        os << group.metaModelIdentifier_;
        return os;
    }
};
}  // namespace exec
}  // namespace nosal
}  // namespace netaos

#endif  // NOSAL_EXEC_FUNCTION_GROUP_H
